package com.example.deepai.service;

import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collections;
import java.util.Random;
import java.util.Map;

// 添加导入
import java.util.List;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
@Service
public class QwenVisionService {
    @Value("${dashscope.api.key}")
    private String apiKey;
    
    private final KnowledgeGraphService knowledgeGraphService;
    
    @Autowired
    public QwenVisionService(KnowledgeGraphService knowledgeGraphService) {
        this.knowledgeGraphService = knowledgeGraphService;
    }
    
    // 更新系统提示，使其更专注于识别图表和交互方式
    public String analyzeImage(String base64Image, String prompt) {
        try {
            MultiModalConversation conv = new MultiModalConversation();
            
            // 更新系统提示，明确要求识别图表类型和交互方式
            MultiModalMessage systemMessage = MultiModalMessage.builder()
                .role(Role.SYSTEM.getValue())
                .content(Arrays.asList(
                    Collections.singletonMap("text", 
                        "You are a specialized UI analysis assistant. Analyze the image and provide detailed information in JSON format." +
                        " IMPORTANT: Return ONLY the JSON object directly, without any markdown formatting, code blocks, or additional text." +
                        " The JSON should follow this structure:" +
                        "\n{" +
                        "\n  \"elements\": [" +
                        "\n    {" +
                        "\n      \"type\": \"button|input|text|image|list|menu|chart\"," +
                        "\n      \"chart_type\": \"bar|pie|line|scatter|none\"," + // 添加图表类型
                        "\n      \"position\": \"top|bottom|left|right\"," +
                        "\n      \"description\": \"element description\"," +
                        "\n      \"clickable\": true|false," +
                        "\n      \"interactions\": [\"click\", \"double_click\", \"swipe\", \"rotate\"]" + // 添加交互方式
                        "\n    }" +
                        "\n  ]," +
                        "\n  \"layout\": \"description of overall layout\"," +
                        "\n  \"global_interactions\": [\"possible user interactions\"]" +
                        "\n}" +
                        "\n注意：" +
                        "\n1. 列表项、菜单项等可点击的元素应该被识别为button类型，并标记clickable为true。" +
                        "\n2. 对于图表元素，请指定chart_type并详细描述可能的交互方式：" +
                        "\n   - 柱状图(bar)：可以双击放大缩小，左右滑动" +
                        "\n   - 饼图/扇形图(pie)：可以旋转、点击查看详情" +
                        "\n   - 折线图(line)：可以缩放、平移" +
                        "\n3. 如果页面包含多级菜单或列表，请在description中详细描述其结构和层次关系。"
                    )
                ))
                .build();
            
            // 构建用户消息，使用 base64 格式
            MultiModalMessage userMessage = MultiModalMessage.builder()
                .role(Role.USER.getValue())
                .content(Arrays.asList(
                    Collections.singletonMap("image", "data:image/png;base64," + base64Image),  // 添加 data URI scheme
                    Collections.singletonMap("text", prompt)
                ))
                .build();
            
            // 构建请求参数
            MultiModalConversationParam param = MultiModalConversationParam.builder()
                .apiKey(apiKey)
                .model("qwen-vl-plus")
                .messages(Arrays.asList(systemMessage, userMessage))
                .build();
            
            // 调用 API 并处理响应
            MultiModalConversationResult result = conv.call(param);
            String response = extractTextFromResult(result);
            
            // 存储分析结果到知识图谱并获取相似分析
            if (response != null && !response.isEmpty()) {
                float[] embedding = generateEmbedding(response);
                
                // 尝试存储分析结果，但不影响主流程
                try {
                    knowledgeGraphService.storeAnalysis(
                        detectImageType(response),
                        response,
                        embedding
                    );
                } catch (Exception e) {
                    log.warn("存储分析结果到知识图谱失败: {}", e.getMessage());
                    // 继续执行，不中断流程
                }
                
                // 尝试查找相似分析，如果失败则返回空列表
                List<String> similarAnalyses;
                try {
                    similarAnalyses = knowledgeGraphService.searchSimilarAnalysis(embedding);
                } catch (Exception e) {
                    log.warn("查找相似分析失败: {}", e.getMessage());
                    similarAnalyses = Collections.emptyList();
                }
                
                // 即使知识图谱操作失败，也返回当前分析结果
                return enrichResponse(response, similarAnalyses);
            }
            
            return response;
            
        } catch (Exception e) {
            log.error("通义千问API调用失败", e);
            return "{\"error\": \"Analysis failed\", \"message\": \"" + 
                e.getMessage().replace("\"", "'") + "\"}";
        }
    }
    
    // 添加辅助方法
    private String extractTextFromResult(MultiModalConversationResult result) {
        if (result == null || result.getOutput() == null) {
            return null;
        }
        try {
            Map<String, Object> content = (Map<String, Object>) result.getOutput()
                .getChoices().get(0).getMessage().getContent().get(0);
            return (String) content.get("text");
        } catch (Exception e) {
            log.error("提取响应文本失败", e);
            return null;
        }
    }
    
    private String detectImageType(String response) {
        try {
            JSONObject json = new JSONObject(response);
            if (json.has("elements") && json.getJSONArray("elements").length() > 0) {
                JSONObject firstElement = json.getJSONArray("elements").getJSONObject(0);
                String type = firstElement.optString("type", "unknown");
                
                // 如果是图表类型，进一步细分
                if ("chart".equals(type) && firstElement.has("chart_type")) {
                    return "chart_" + firstElement.getString("chart_type");
                }
                return type;
            }
        } catch (Exception e) {
            log.debug("响应不是有效的 JSON 格式或没有预期的结构: {}", e.getMessage());
            // 尝试从文本中推断类型
            String lowerResponse = response.toLowerCase();
            
            // 检测图表类型
            if (lowerResponse.contains("柱状图") || lowerResponse.contains("bar chart")) {
                return "chart_bar";
            } else if (lowerResponse.contains("饼图") || lowerResponse.contains("扇形图") || 
                       lowerResponse.contains("pie chart")) {
                return "chart_pie";
            } else if (lowerResponse.contains("折线图") || lowerResponse.contains("line chart")) {
                return "chart_line";
            } else if (lowerResponse.contains("图表") || lowerResponse.contains("chart")) {
                return "chart";
            }
            
            // 检测列表或菜单结构
            if (lowerResponse.contains("列表") || lowerResponse.contains("菜单") || 
                lowerResponse.contains("list") || lowerResponse.contains("menu")) {
                return "list_menu";
            }
            
            // 其他常规类型检测
            if (lowerResponse.contains("button") || lowerResponse.contains("按钮")) {
                return "button";
            } else if (lowerResponse.contains("input") || lowerResponse.contains("输入")) {
                return "input";
            } else if (lowerResponse.contains("image") || lowerResponse.contains("图片")) {
                return "image";
            } else if (lowerResponse.contains("text") || lowerResponse.contains("文本")) {
                return "text";
            }
        }
        return "unknown";
    }
    
    private float[] generateEmbedding(String text) {
        try {
            // 使用简单的哈希算法生成向量
            float[] embedding = new float[128];
            int hash = text.hashCode();
            Random random = new Random(hash);
            
            for (int i = 0; i < embedding.length; i++) {
                embedding[i] = random.nextFloat() * 2 - 1; // 生成-1到1之间的随机数
            }
            
            // 归一化向量
            float sum = 0;
            for (float value : embedding) {
                sum += value * value;
            }
            float norm = (float) Math.sqrt(sum);
            for (int i = 0; i < embedding.length; i++) {
                embedding[i] /= norm;
            }
            
            return embedding;
        } catch (Exception e) {
            log.error("生成文本嵌入向量失败", e);
            return new float[128]; // 返回零向量作为后备
        }
    }
    
    // 添加一个新方法，用于从响应中提取JSON代码块
    private String extractJsonFromMarkdown(String response) {
        try {
            // 查找Markdown代码块
            int jsonStart = response.indexOf("```json");
            if (jsonStart != -1) {
                jsonStart = response.indexOf("\n", jsonStart) + 1;
                int jsonEnd = response.indexOf("```", jsonStart);
                if (jsonEnd != -1) {
                    // 提取JSON部分
                    String jsonContent = response.substring(jsonStart, jsonEnd).trim();
                    // 验证是否为有效JSON
                    try {
                        new JSONObject(jsonContent);
                        return jsonContent;
                    } catch (Exception e) {
                        log.warn("从Markdown代码块提取的内容不是有效的JSON: {}", e.getMessage());
                    }
                }
            }
            return null;
        } catch (Exception e) {
            log.error("从Markdown提取JSON失败: {}", e.getMessage());
            return null;
        }
    }
    
    private String enrichResponse(String originalResponse, List<String> similarAnalyses) {
        try {
            // 首先尝试从Markdown代码块中提取JSON
            String jsonContent = extractJsonFromMarkdown(originalResponse);
            
            // 尝试解析原始响应或提取的JSON内容
            JSONObject currentAnalysis;
            if (jsonContent != null) {
                try {
                    currentAnalysis = new JSONObject(jsonContent);
                    log.info("成功从Markdown代码块中提取JSON");
                } catch (Exception e) {
                    log.warn("从Markdown提取的内容不是有效的JSON: {}", e.getMessage());
                    currentAnalysis = new JSONObject();
                    currentAnalysis.put("text", originalResponse);
                }
            } else {
                try {
                    currentAnalysis = new JSONObject(originalResponse);
                } catch (Exception e) {
                    log.warn("原始响应不是有效的JSON格式，将作为纯文本处理: {}", e.getMessage());
                    // 如果不是有效的JSON，则将其作为纯文本包装
                    currentAnalysis = new JSONObject();
                    currentAnalysis.put("text", originalResponse);
                }
            }
            
            // 提取图表交互信息
            JSONObject chartInteractions = extractChartInteractions(originalResponse);
            
            // 创建最终响应
            JSONObject response = new JSONObject();
            response.put("current_analysis", currentAnalysis);
            response.put("similar_cases", similarAnalyses);
            
            // 添加图表交互信息
            if (chartInteractions.optBoolean("has_chart", false)) {
                response.put("chart_interactions", chartInteractions);
            }
            
            // 如果从Markdown提取了JSON，添加一个标志
            if (jsonContent != null) {
                response.put("extracted_from_markdown", true);
            }
            
            return response.toString();
        } catch (Exception e) {
            log.error("合并响应失败: {}", e.getMessage());
            // 返回原始响应，确保至少有一些数据返回给客户端
            return originalResponse;
        }
    }
    
    /**
     * 从响应中提取图表交互信息
     * @param response 原始响应
     * @return 包含图表交互信息的JSON对象
     */
    private JSONObject extractChartInteractions(String response) {
        JSONObject result = new JSONObject();
        try {
            // 首先尝试解析为JSON
            JSONObject json = null;
            try {
                // 尝试直接解析
                json = new JSONObject(response);
            } catch (Exception e) {
                // 尝试从Markdown提取
                String jsonContent = extractJsonFromMarkdown(response);
                if (jsonContent != null) {
                    json = new JSONObject(jsonContent);
                }
            }
            
            if (json != null && json.has("elements")) {
                JSONObject chartInfo = new JSONObject();
                boolean hasChart = false;
                
                // 遍历所有元素，查找图表
                for (int i = 0; i < json.getJSONArray("elements").length(); i++) {
                    JSONObject element = json.getJSONArray("elements").getJSONObject(i);
                    String type = element.optString("type", "");
                    
                    if ("chart".equals(type) || type.startsWith("chart_")) {
                        hasChart = true;
                        String chartType = element.optString("chart_type", "unknown");
                        chartInfo.put("chart_type", chartType);
                        
                        // 提取交互方式
                        if (element.has("interactions")) {
                            chartInfo.put("interactions", element.getJSONArray("interactions"));
                        } else {
                            // 根据图表类型推断默认交互方式
                            JSONObject defaultInteractions = new JSONObject();
                            if ("bar".equals(chartType)) {
                                defaultInteractions.put("interactions", 
                                    Arrays.asList("双击放大缩小", "左右滑动", "点击查看详情"));
                            } else if ("pie".equals(chartType)) {
                                defaultInteractions.put("interactions", 
                                    Arrays.asList("旋转", "点击查看详情"));
                            } else if ("line".equals(chartType)) {
                                defaultInteractions.put("interactions", 
                                    Arrays.asList("缩放", "平移", "点击查看数据点"));
                            }
                            chartInfo.put("default_interactions", defaultInteractions);
                        }
                        
                        // 提取描述
                        if (element.has("description")) {
                            chartInfo.put("description", element.getString("description"));
                        }
                        
                        result.put("chart_" + i, chartInfo);
                    }
                }
                
                result.put("has_chart", hasChart);
            }
            
            return result;
        } catch (Exception e) {
            log.error("提取图表交互信息失败: {}", e.getMessage());
            return result;
        }
    }
}